import { View, Map, Feature } from 'ol';
import { Projection, addProjection, useGeographic, get, transformExtent } from 'ol/proj';
import { defaults as controlDefaults } from 'ol/control/defaults';
import { defaults as interactionDefaults } from 'ol/interaction/defaults';
import CircleStyle from 'ol/style/Circle';
import { Style, Fill, Text, Stroke, Icon } from 'ol/style';
import { LineString, MultiPolygon, Point, Polygon } from 'ol/geom';
import VectorSource from 'ol/source/Vector';
import { Cluster, VectorTile, XYZ } from 'ol/source';
import VectorLayer from 'ol/layer/Vector';
import VectorImage from 'ol/layer/VectorImage';
import TileLayer from 'ol/layer/Tile';
import Heatmap from 'ol/layer/Heatmap';
import VectorTileLayer from 'ol/layer/VectorTile';
import GeoJSON from 'ol/format/GeoJSON';
import MVT from 'ol/format/MVT';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import * as olExtent from 'ol/extent';
import WMTS from 'ol/source/WMTS';
import { FlyLine } from './flyLine';
/**
 * openlayer工具类
 */
class OlUtil {
    constructor() {
        Object.defineProperty(this, "map", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.map = undefined;
    }
    /**
     * 实例化ol/Map对象
     * @param mapContainer  HTMLElement | string | undefined 渲染地图dom的id
     * @param {InitMapOptions} options  可选配置项
     * @returns 实例化ol/Map对象
     */
    initMap(mapContainer, options) {
        useGeographic(); // api使用4326坐标系
        this.map = new Map({
            target: mapContainer,
            view: new View({
                projection: options.projection || 'EPSG:3857',
                center: options.center,
                zoom: options.zoom || 8,
                minZoom: options.minZoom || 6,
                maxZoom: options.maxZoom || 18,
                constrainResolution: options.constrainResolution || true, // 设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别
                enableRotation: options.enableRotation || false // 设置是否允许旋转
            }),
            layers: options.layers,
            controls: controlDefaults({ zoom: false, rotate: false }), // 隐藏缩放及旋转按钮
            interactions: interactionDefaults({ doubleClickZoom: options.doubleClickZoom || false }) // 禁用双击缩放
        });
        return this.map;
    }
    /**
     * 获取指定id的图层
     * @param id string 图层id
     * @returns OlBaseLayer | undefined 图层对象
     */
    getLayer(id) {
        if (!this.map)
            return;
        return this.map
            .getLayers()
            .getArray()
            .find(function (layer) {
            const layerId = layer.get('id');
            return layerId && layerId === id;
        });
    }
    /**
     * 删除指定id的图层
     * @param id string 图层id
     */
    removeLayer(id) {
        if (!this.map)
            return;
        const delLayer = this.map
            .getLayers()
            .getArray()
            .find(function (layer) {
            const layerId = layer.get('id');
            return layerId && layerId === id;
        });
        delLayer && this.map.removeLayer(delLayer);
    }
    /**
     * 设置图层显示隐藏
     * @param id string 图层id
     * @param visible boolean 是否显示
     */
    setLayerVisible(id, visible) {
        const layer = this.getLayer(id);
        layer && layer.setVisible(visible);
    }
    /**
     * 设置图层透明度
     * @param id string 图层id
     * @param opacity number 0-1 透明度
     */
    // 设置图层透明度 id:string 图层id opacity:number 0-1 透明度
    setLayerOpacity(id, opacity) {
        const layer = this.getLayer(id);
        layer && layer.setOpacity(opacity);
    }
    /**
     * 创建点类型的图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param {PointLayerOptions} options  配置项
     * @returns VectorLayer | undefined
     */
    createPointsLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        let style = new Style({
            image: new CircleStyle({
                radius: 10,
                fill: new Fill({
                    color: '#f00'
                })
            })
        });
        style = options.style || style;
        // 设置聚合的圆点的放大样式
        const clusterScaleStyle = style.clone();
        let clusterRadius = style.getImage().getRadius() * 1.5;
        if (clusterRadius < 10) {
            // 防止聚合点位过小
            clusterRadius = 15;
        }
        ;
        (clusterScaleStyle?.getImage()).setRadius(clusterRadius);
        if (dataArr && dataArr.length > 0) {
            let source;
            const vectorSource = new VectorSource();
            let vectorLayer = undefined;
            dataArr.forEach((res, index) => {
                const x = Number(res.longitude) || Number(res.x);
                const y = Number(res.latitude) || Number(res.y);
                let feature = new Feature({
                    geometry: new Point([x, y]),
                    attributes: res,
                    c_name: 'point_' + index // 保证唯一性，在聚合显示时用于区分独立的 style
                });
                if (res.style) {
                    feature.setStyle(res.style);
                }
                vectorSource.addFeature(feature);
            });
            if (options.cluster) {
                const clusterSource = new Cluster({
                    distance: options.distance || 20,
                    source: vectorSource
                });
                source = clusterSource;
                const styleCache = {};
                vectorLayer = new VectorLayer({
                    source: source,
                    visible: options.visible,
                    style: function (feature) {
                        const size = feature.get('features').length;
                        let _style;
                        if (size === 1) {
                            // 当前的标注仅包含一个feature时，采用该feature的样式显示，而不是统一聚合样式。
                            _style = styleCache[feature.get('features')[0].get('c_name')];
                        }
                        else {
                            _style = styleCache[size];
                        }
                        if (!_style) {
                            _style = (options && options.clusterStyle) || [
                                new Style({
                                    image: clusterScaleStyle.getImage(),
                                    text: new Text({
                                        text: size.toString(),
                                        scale: 1.2,
                                        stroke: new Stroke({
                                            color: 'white',
                                            width: 2
                                        }),
                                        fill: new Fill({
                                            color: 'black'
                                        })
                                    })
                                })
                            ];
                            if (size === 1) {
                                // 这里采用那么作为styleCache对象key的值，c_name是唯一的，
                                // 这样就可以为为每一个feature设置不同的样式，因为起初feature未聚合前，
                                // 可能会用使用不同的图标来表示不同的目标
                                const pkiaa = feature.get('features')[0].get('c_name');
                                _style = feature.get('features')[0].getStyle();
                                styleCache[pkiaa] = _style;
                            }
                            else {
                                styleCache[size] = _style;
                            }
                        }
                        return _style;
                    }
                });
            }
            else {
                source = vectorSource;
                vectorLayer = new VectorLayer({
                    source: source,
                    visible: options.visible
                });
                vectorLayer.setStyle(style);
            }
            vectorLayer.set('id', id); // 给图层赋予id
            map && map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!图层创建失败');
        }
    }
    /**
     * 创建图片标记符号的图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param { PictureMarkerLayerOptions } options  配置项
     * @returns VectorImage | undefined
     */
    createPictureMarkerLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        let style = new Style({
            image: new Icon({
                anchor: [0.5, 0.5], // 锚点
                opacity: 1,
                width: 64,
                height: 64,
                src: 'map/img/default.png'
            })
        });
        style = options.style || style;
        if (dataArr && dataArr.length > 0) {
            let source;
            let vectorLayer = undefined;
            const vectorSource = new VectorSource();
            dataArr.forEach((res, index) => {
                const x = Number(res.longitude) || Number(res.x);
                const y = Number(res.latitude) || Number(res.y);
                let feature = new Feature({
                    geometry: new Point([x, y]),
                    attributes: res,
                    c_name: 'point_' + index // 保证唯一性，在聚合显示时用于区分独立的 style
                });
                if (res.style) {
                    feature.setStyle(res.style);
                }
                vectorSource.addFeature(feature);
            });
            if (options.cluster) {
                const clusterSource = new Cluster({
                    distance: options.distance || 80,
                    source: vectorSource
                });
                source = clusterSource;
                const styleCache = {};
                vectorLayer = new VectorImage({
                    source: source,
                    visible: options.visible,
                    style: function (feature) {
                        const size = feature.get('features').length;
                        let _style;
                        if (size === 1) {
                            // 当前的标注仅包含一个feature时，采用该feature的样式显示，而不是统一聚合样式。
                            _style = styleCache[feature.get('features')[0].get('c_name')];
                        }
                        else {
                            _style = styleCache[size];
                        }
                        if (!_style) {
                            _style = (options && options.clusterStyle) || [
                                new Style({
                                    image: style.clone().getImage(),
                                    text: new Text({
                                        text: size.toString(),
                                        scale: 1.3,
                                        stroke: new Stroke({
                                            color: 'white',
                                            width: 1
                                        }),
                                        fill: new Fill({
                                            color: 'black'
                                        }),
                                        offsetY: (options && options.textOffsetY) || 10
                                    })
                                })
                            ];
                            if (size === 1) {
                                // 这里采用那么作为styleCache对象key的值，c_name是唯一的，
                                // 这样就可以为为每一个feature设置不同的样式，因为起初feature未聚合前，
                                // 可能会用使用不同的图标来表示不同的目标
                                const pkiaa = feature.get('features')[0].get('c_name');
                                _style = feature.get('features')[0].getStyle();
                                styleCache[pkiaa] = _style;
                            }
                            else {
                                styleCache[size] = _style;
                            }
                        }
                        return _style;
                    }
                });
            }
            else {
                source = vectorSource;
                vectorLayer = new VectorImage({
                    source: source,
                    visible: options.visible
                });
                vectorLayer.setStyle(style);
            }
            vectorLayer.set('id', id);
            map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!');
        }
    }
    /**
     * 创建文字标记符号图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param {TextMarkerLayerOptions} options  配置项
     * @returns VectorLayer | undefined
     */
    // (showTextKey:string 需要显示的字段名称 style:obj 点的样式 visible:boolean 图层是否显示)
    createTextMarkerLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        options.showTextKey = options.showTextKey || 'name';
        if (options.visible === undefined) {
            options.visible = true;
        }
        const createItemStyle = (showText) => {
            return new Style({
                text: new Text({
                    textAlign: 'center', // 位置
                    textBaseline: 'middle', // 基准线
                    // font: 'normal 16px 微软雅黑', // 文字样式
                    scale: 1.8,
                    text: showText, // 文本内容
                    stroke: new Stroke({
                        color: 'white',
                        width: 2
                    }),
                    fill: new Fill({
                        color: 'black'
                    })
                })
            });
        };
        if (dataArr && dataArr.length > 0) {
            const source = new VectorSource();
            dataArr.forEach((res) => {
                const x = Number(res.longitude) || Number(res.x);
                const y = Number(res.latitude) || Number(res.y);
                let feature = new Feature({
                    geometry: new Point([x, y]),
                    attributes: res
                });
                if (res.style) {
                    feature.setStyle(res.style);
                }
                else {
                    feature.setStyle(options.style ||
                        (options.showTextKey && res[options.showTextKey] && createItemStyle(res[options.showTextKey])));
                }
                source.addFeature(feature);
            });
            const vectorLayer = new VectorLayer({
                source: source,
                visible: options.visible
            });
            vectorLayer.set('id', id); // 给图层赋予id
            map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!');
        }
    }
    /**
     * 创建线类型图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param {LineLayerOptions}options  配置项
     * @returns VectorLayer | undefined
     */
    createLineLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        let style = new Style({
            stroke: new Stroke({
                color: '#f00',
                width: 2
            })
        });
        style = options.style || style;
        if (dataArr && dataArr.length > 0) {
            const source = new VectorSource();
            dataArr.forEach((res) => {
                const paths = [];
                res.paths.forEach((_res) => {
                    paths.push([Number(_res[0]), Number(_res[1])]);
                });
                const feature = new Feature({
                    geometry: new LineString(paths),
                    attributes: res
                });
                if (res.style) {
                    feature.setStyle(res.style);
                }
                source.addFeature(feature);
            });
            const vectorLayer = new VectorLayer({
                source: source,
                visible: options.visible
            });
            vectorLayer.setStyle(style);
            vectorLayer.set('id', id); // 给图层赋予id
            map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!');
        }
    }
    /**
     * 创建多边形类型图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param {PolygonLayerOptions}options  配置项
     * @returns VectorLayer | undefined
     */
    createPolygonLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        let style = new Style({
            stroke: new Stroke({
                color: '#f00',
                width: 2
            }),
            fill: new Fill({
                color: '#ffb100d9'
            })
        });
        style = options.style || style;
        if (dataArr && dataArr.length > 0) {
            const source = new VectorSource();
            dataArr.forEach((res) => {
                let geometry;
                if (res.multiRings && res.multiRings.length > 0) {
                    geometry = new MultiPolygon([res.multiRings]);
                }
                else {
                    const rings = [];
                    res.rings.forEach((_res) => {
                        rings.push([Number(_res[0]), Number(_res[1])]);
                    });
                    geometry = new Polygon([rings]);
                }
                const feature = new Feature({
                    geometry: geometry,
                    attributes: res
                });
                if (res.style) {
                    feature.setStyle(res.style);
                }
                source.addFeature(feature);
            });
            const vectorLayer = new VectorLayer({
                source: source,
                visible: options.visible
            });
            vectorLayer.setStyle(style);
            vectorLayer.set('id', id); // 给图层赋予id
            map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!');
        }
    }
    /**
     * 创建geojson图层
     * @param id string 图层id
     * @param data ArrayBuffer | Document | Element | Object | string，geojson数据源
     * @param {GeojsonLayerOptions}options  配置项
     * @returns VectorLayer | undefined
     */
    // 创建geojson图层 id:string 图层的id data:Array geojson对象，包含点位及相关信息 options:Obj 相关配置项（visible:boolean 图层是否显示）
    createGeojsonLayer(id, data, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        let style = new Style({
            stroke: new Stroke({
                color: '#f00',
                width: 2
            }),
            fill: new Fill({
                color: '#ffb100d9'
            })
        });
        style = options.style || style;
        if (data) {
            const source = new VectorSource({
                features: new GeoJSON().readFeatures(data, {
                    dataProjection: 'EPSG:4326'
                })
            });
            const vectorLayer = new VectorLayer({
                source: source,
                style: style,
                visible: options.visible
            });
            vectorLayer.set('id', id); // 给图层赋予id
            map.addLayer(vectorLayer);
            return vectorLayer;
        }
        else {
            console.log('传入数据错误!');
        }
    }
    /**
     * 创建热力图层
     * @param id string 图层id
     * @param dataArr Array<any> 对象数组，包含点位及相关信息
     * @param {HeatMapLayerOptions}options  配置项
     * @returns Heatmap | undefined
     */
    createHeatMapLayer(id, dataArr, options) {
        const map = this.map;
        if (!map)
            return;
        options = options || {};
        if (options.visible === undefined) {
            options.visible = true;
        }
        options.cntStr = options.cntStr || 'cnt';
        if (dataArr && dataArr.length > 0) {
            const source = new VectorSource();
            const cntArr = [];
            dataArr.forEach((res) => {
                if (!res[options.cntStr]) {
                    res[options.cntStr] = 1;
                }
                else {
                    res[options.cntStr] = Number(res[options.cntStr]);
                }
                cntArr.push(res[options.cntStr]);
            });
            const maxCnt = Math.max.apply(null, cntArr);
            const minCnt = Math.min.apply(null, cntArr);
            dataArr.forEach((res) => {
                if (maxCnt === minCnt) {
                    res.weight = 1; // weight为0到1之间
                }
                else {
                    res.weight = (res[options.cntStr] - minCnt) / (maxCnt - minCnt) || 0.1;
                }
                const x = Number(res.longitude) || Number(res.x);
                const y = Number(res.latitude) || Number(res.y);
                let feature = new Feature({
                    geometry: new Point([x, y]),
                    weight: res.weight,
                    attributes: res
                });
                source.addFeature(feature);
            });
            const heatMapLayer = new Heatmap({
                source: source,
                radius: options.radius || 8, // 热点半径
                blur: options.blur || 15, // 模糊尺寸
                weight: (feature) => {
                    return feature.get('weight');
                },
                visible: options.visible
            });
            heatMapLayer.set('id', id); // 给图层赋予id
            map.addLayer(heatMapLayer);
            return heatMapLayer;
        }
    }
    /**
     * 加载XYZ图层
     * @param {XYZLayerOptions}options  配置项
     * @returns TileLayer
     */
    loadXYZLayer(options) {
        if (options.visible === undefined) {
            options.visible = true;
        }
        const xyzLayer = new TileLayer({
            source: new XYZ({
                url: options.url,
                projection: options.projection, // 坐标系
                tileGrid: options.tileGrid, // 网格信息
                crossOrigin: options.crossOrigin || null // 跨域设置
            }),
            visible: options.visible
        });
        xyzLayer.set('id', options.id);
        return xyzLayer;
    }
    /**
     * 加载矢量切片图层
     * @param {VectorTileLayerOptions}options  配置项
     * @returns VectorTileLayer
     */
    loadVectorTileLayer(options) {
        const vectorTileLayer = new VectorTileLayer({
            source: new VectorTile({
                format: new MVT(),
                url: options.url,
                tileGrid: new WMTSTileGrid({
                    origin: (options.projection && olExtent.getTopLeft(options.projection.getExtent())) || undefined,
                    resolutions: options.resolutions,
                    matrixIds: options.matrixIds,
                    tileSize: options.tileSize || 256
                }),
                projection: options.projection // 投影坐标系
            })
        });
        vectorTileLayer.set('id', options.id);
        return vectorTileLayer;
    }
    /**
     * 加载WMTS图层
     * @param {WMTSLayerOptions}options  配置项
     * @returns TileLayer
     */
    loadWMTSLayer(options) {
        const tilelayer = new TileLayer({
            source: new WMTS({
                url: options.url, // 服务url
                layer: options.layer || '', // 需要加载的图层id
                version: options.version || '1.0.0', // WMTS版本
                style: options.style || '', // Style name as advertised in the WMTS capabilities.
                matrixSet: options.matrixSet, // 投影坐标系矩阵集，一定要和WMTS capabilities文档中一致，否则会加载失败
                format: options.format || 'image/png', // 图像格式,仅在请求编码为“KVP”时使用
                // 平铺方案
                tileGrid: new WMTSTileGrid({
                    origin: (options.projection && olExtent.getTopLeft(options.projection.getExtent())) || undefined,
                    resolutions: options.resolutions,
                    matrixIds: options.matrixIds
                }),
                projection: options.projection, // 投影坐标系
                crossOrigin: options.crossOrigin || null // 跨域设置
            })
        });
        tilelayer.set('id', options.id);
        return tilelayer;
    }
    /**
     * 自定义4490坐标系并注册 (此时的分辨率及层级矩阵为空，需要getResolutionsAndMids方法按实际需求设置)
     * @returns Projection
     */
    defineProjection_4490() {
        // 自定义坐标系
        const projection_4490 = new Projection({
            code: 'EPSG:4490',
            units: 'degrees',
            axisOrientation: 'enu'
        });
        projection_4490.setExtent([-180, -90, 180, 90]);
        projection_4490.setWorldExtent([-180, -90, 180, 90]);
        addProjection(projection_4490);
        return projection_4490;
    }
    /**
     * 获取分辨率和层级矩阵
     * @param projection Projection 参考坐标系
     * @param defineSize number 切片分辨率 (默认256 一般为256*256或512*512)
     * @param minZoom number 最小层级
     * @param maxZoom number 最大层级
     * @returns ResolutionsAndMids
     */
    getResolutionsAndMids(projection, defineSize, minZoom, maxZoom) {
        minZoom = minZoom || 0;
        maxZoom = maxZoom || 20;
        defineSize = defineSize || 256;
        const projection4326 = get('EPSG:4326');
        const projections = projection || projection4326;
        const projectionExtent = projections.getExtent();
        const size = olExtent.getWidth(projectionExtent) / defineSize; // size就是一个像素代表的经纬度
        const matrixIds = [];
        const resolutions = [];
        for (let z = minZoom; z < maxZoom; ++z) {
            resolutions[z] = size / Math.pow(2, z);
            matrixIds[z] = z.toString();
        }
        return { resolutions: resolutions, matrixIds: matrixIds };
    }
    /**
     * 定位到指定图层
     * @param id string 图层id
     * @param {GoToLayerOptions}options  配置项
     */
    goToLayer(id, options) {
        options = options || {};
        if (options.duration === undefined) {
            options.duration = 200;
        }
        const layer = this.getLayer(id);
        if (!layer) {
            console.log('图层不存在!');
            return;
        }
        let _extent = [];
        // 判断图层是否为聚合图层
        const ifClusterLayer = layer && layer.getSource() instanceof Cluster;
        if (ifClusterLayer) {
            const source = layer.getSource();
            const _source = source.getSource();
            const clusterExtent = _source && _source.getExtent();
            const width = clusterExtent && olExtent.getWidth(clusterExtent);
            const height = clusterExtent && olExtent.getHeight(clusterExtent);
            const extent = clusterExtent;
            if (extent && width && height) {
                _extent = [extent[0] - width * 0.1, extent[1] - height * 0.1, extent[2] + width * 0.1, extent[3] + height * 0.1];
            }
        }
        else {
            if (layer) {
                const source = layer.getSource();
                if (source) {
                    if (source.getExtent) {
                        const width = olExtent.getWidth(source.getExtent());
                        const height = olExtent.getHeight(source.getExtent());
                        const extent = source.getExtent();
                        _extent = [
                            extent[0] - width * 0.1,
                            extent[1] - height * 0.1,
                            extent[2] + width * 0.1,
                            extent[3] + height * 0.1
                        ];
                    }
                    else {
                        const allFeatures = source.getFeaturesInExtent([-180, -90, 180, 90]);
                        let coordinates = [];
                        allFeatures.forEach((item) => {
                            const itemExtent = item.getExtent();
                            coordinates.push([itemExtent[0], itemExtent[1]]);
                            coordinates.push([itemExtent[2], itemExtent[3]]);
                        });
                        _extent = olExtent.boundingExtent(coordinates);
                    }
                }
            }
        }
        if (_extent && _extent.length > 0) {
            this.map &&
                this.map.getView().fit(_extent, {
                    duration: options.duration,
                    callback: options.callback
                });
        }
    }
    /**
     * 定位到指定点
     * @param {CenterAndZoomOptions}options  配置项
     */
    setCenterAndZoom(options) {
        if (options.duration === undefined) {
            options.duration = 500;
        }
        this.map &&
            this.map.getView().animate({
                center: options.center,
                zoom: options.zoom,
                duration: options.duration,
                easing: (percent) => {
                    if (percent === 1) {
                        // 定位过程的百分比
                        options.callback && options.callback();
                    }
                    return percent;
                }
            });
    }
    /**
     * 定位到指定要素
     * @param feature Feature 要素对象
     * @param {goToFeatureOptions}options  配置项
     */
    goToFeature(feature, options) {
        options = options || {};
        if (options.duration === undefined) {
            options.duration = 500;
        }
        const geometry = feature.getGeometry();
        const extent = geometry && geometry.getExtent();
        if (extent) {
            const _extent = olExtent.buffer(extent, 0.3); // 计算缓冲区
            this.map &&
                this.map.getView().fit(_extent, {
                    duration: options.duration,
                    callback: options.callback
                });
        }
    }
    /**
     * 创建飞线图
     * @param dataArr Array<any> 数据数组
     * @param {FlyLineOptions}options  配置项
     */
    createFlyLine(dataArr, options) {
        if (!this.map) {
            return;
        }
        const { parentDom, callback } = options;
        if (dataArr && dataArr.length > 0) {
            var series = [];
            var effectSymbol; // 特效图形样式
            var effectSize; // 特效图形大小
            var lineWith; // 线的宽度
            // effectSymbol =   'image://' + pathSvg 加载图片的方式
            dataArr.forEach((item) => {
                if (item.type === 'airplane') {
                    effectSize = 25;
                    effectSymbol =
                        'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z';
                }
                else if (item.type === 'car') {
                    effectSize = 25;
                    effectSymbol =
                        'path://M512 0c153.173333 0 277.333333 124.16 277.333333 277.333333v136.106667h42.666667a34.56 34.56 0 1 1 0 69.12h-42.666667V832a192 192 0 0 1-192 192h-170.666666a192 192 0 0 1-192-192V482.56H192a34.56 34.56 0 0 1-3.136-68.970667L192 413.44h42.666667V277.333333c0-153.173333 124.16-277.333333 277.333333-277.333333z m213.354667 775.552C663.402667 797.824 590.293333 810.666667 512 810.666667c-78.293333 0-151.381333-12.842667-213.333333-35.093334V832a128 128 0 0 0 128 128h170.666666a128 128 0 0 0 128-128l0.021334-56.448zM512 405.333333c-46.912 0-92.309333 5.077333-134.186667 14.634667C395.669333 465.045333 405.333333 519.210667 405.333333 576c0 56.810667-9.642667 110.933333-27.541333 156.032C419.690667 741.589333 465.066667 746.666667 512 746.666667c46.912 0 92.309333-5.077333 134.186667-14.634667C628.330667 686.954667 618.666667 632.789333 618.666667 576c0-53.013333 8.384-103.722667 24.064-146.901333l3.477333-9.130667-12.672-2.730667A612.992 612.992 0 0 0 512 405.333333z m213.333333 0c-25.92 38.912-42.666667 100.885333-42.666666 170.666667s16.746667 131.754667 42.666666 170.666667V405.333333z m-426.666666 0l0.021333 341.290667C324.586667 707.690667 341.333333 645.76 341.333333 576c0-69.781333-16.746667-131.733333-42.666666-170.666667zM512 64c-117.824 0-213.333333 95.509333-213.333333 213.333333v99.114667C360.618667 354.176 433.706667 341.333333 512 341.333333s151.381333 12.842667 213.333333 35.093334V277.333333c0-117.824-95.509333-213.333333-213.333333-213.333333z m95.445333 76.608l2.986667 0.96 40.106667 14.592a34.56 34.56 0 0 1-20.650667 65.898667l-2.986667-0.96-40.106666-14.592a34.56 34.56 0 0 1 20.650666-65.898667z m-149.589333 21.610667a34.56 34.56 0 0 1-17.749333 43.093333l-2.901334 1.194667-40.106666 14.592a34.56 34.56 0 0 1-26.538667-63.744l2.901333-1.194667 40.106667-14.592a34.56 34.56 0 0 1 44.288 20.650667z';
                }
                else {
                    effectSize = 15;
                    effectSymbol = 'triangle';
                }
                lineWith = item.flyWireWidth || 1;
                series.push({
                    type: 'lines',
                    coordinateSystem: 'openlayers',
                    zlevel: 1,
                    effect: {
                        show: true,
                        period: 6,
                        trailLength: 0.7,
                        color: '#fff',
                        symbolSize: lineWith + 1
                    },
                    lineStyle: {
                        normal: {
                            color: item.color,
                            width: 0,
                            curveness: 0.2
                        }
                    },
                    tooltip: {
                        trigger: 'item',
                        show: false
                    },
                    data: item.data
                }, {
                    type: 'lines',
                    coordinateSystem: 'openlayers',
                    zlevel: 2,
                    symbol: ['none', 'arrow'],
                    symbolSize: 10,
                    effect: {
                        show: true,
                        period: 6,
                        trailLength: 0,
                        symbol: effectSymbol,
                        symbolSize: effectSize
                    },
                    lineStyle: {
                        normal: {
                            color: item.color,
                            width: lineWith,
                            opacity: 0.6,
                            curveness: 0.2
                        }
                    },
                    tooltip: {
                        trigger: 'item',
                        formatter: (param) => {
                            callback && callback(param);
                            return `${param.data.fromName} > ${param.data.toName} ${param.data.value}`;
                        },
                        show: true
                    },
                    data: item.data
                }, {
                    type: 'effectScatter',
                    coordinateSystem: 'openlayers',
                    zlevel: 2,
                    rippleEffect: {
                        brushType: 'stroke'
                    },
                    label: {
                        normal: {
                            show: true,
                            position: 'bottom',
                            formatter: '{b}'
                        }
                    },
                    tooltip: {
                        trigger: 'item',
                        show: false
                    },
                    symbolSize: 10,
                    itemStyle: {
                        normal: {
                            color: item.color
                        }
                    },
                    data: item.data.map(function (dataItem) {
                        return {
                            name: dataItem.fromName,
                            value: dataItem.coords[0]
                        };
                    })
                }, {
                    type: 'effectScatter',
                    coordinateSystem: 'openlayers',
                    zlevel: 2,
                    rippleEffect: {
                        brushType: 'stroke'
                    },
                    label: {
                        normal: {
                            show: true,
                            position: 'bottom',
                            formatter: '{b}'
                        }
                    },
                    tooltip: {
                        trigger: 'item',
                        show: false
                    },
                    symbolSize: 10,
                    itemStyle: {
                        normal: {
                            color: item.color
                        }
                    },
                    data: item.data.map(function (dataItem) {
                        return {
                            name: dataItem.toName,
                            value: dataItem.coords[1]
                        };
                    })
                });
            });
            var qianxiChart = new FlyLine(this.map, { parentDom });
            var option = {
                tooltip: {
                    trigger: 'item',
                    show: true
                },
                series: series
            };
            qianxiChart.setChartOption(option);
            return qianxiChart;
        }
    }
    /**
     * 检测经纬度是否合法，剔除无效数据
     * @param dataArr Array<any> 数据数组
     * @param {checkLongitudeAndLatitudeOptions} options  配置项
     * @returns Array<any> 有效数据
     */
    checkLongitudeAndLatitude(dataArr, options) {
        const l = [];
        dataArr.forEach((item) => {
            item.x = Number((options && options.longitudeStr && item[options.longitudeStr]) ||
                item.x ||
                item.longitude ||
                item.lng ||
                item.lon ||
                0);
            item.y = Number((options && options.latitudeStr && item[options.latitudeStr]) || item.y || item.latitude || item.lat || 0);
            l.push(item);
        });
        return l;
    }
    /**
     * 限制地图可拖动范围
     * @param {olExtent.Extent}maxExtent 最大范围
     * @param extentProjectionCode string 最大范围的坐标系
     * @returns
     */
    setMapExtent(maxExtent, extentProjectionCode) {
        if (!this.map) {
            console.log('map 不存在！');
            return;
        }
        const view = this.map.getView();
        if (!view) {
            console.log('view 不存在！');
            return;
        }
        const projectionCode = this.map.getView().getProjection().getCode();
        if (!projectionCode) {
            console.log('projectionCode 不存在！');
            return;
        }
        if (!maxExtent) {
            console.log('maxExtent 不存在！');
            return;
        }
        const extent = transformExtent(maxExtent, extentProjectionCode || 'EPSG:4326', projectionCode);
        view.applyOptions_({
            extent,
            constrainOnlyCenter: false, // 如果为true，则区段约束将仅适用于视图中心，而不是整个区段。
            multiWorld: false // 如果为false，则视图受到约束，因此只有一个世界可见，并且您无法平移边缘。如果为true，地图可能会以低缩放级别显示多个世界。仅在投影是全局的情况下使用。请注意，如果还提供了范围，则优先考虑。
        });
    }
}
export { OlUtil };
